import { SClient } from "./signalr";

class PublishSubscribe {
    constructor(){}

    #hubpath = '/srh';
    #http = 'http://';
    #map = new Map();
    /**
     * 打开连接，假如callback不为null,同时注册订阅服务
     * @param {string} url signalr hub url, format: http(s)://host:port/srh
     * @param {Function} callback receive data handler, callback function only one parameter,format: {type: string, group: string, Data: any }
     * @param {rndstr} 内部连接KEY一部分，与url组成key,用于同个url多个连接
     */
    async start(url, callback = null, rndstr = '') {
        const tmp = url === null || url === undefined ? '' : url.toLowerCase().trim();
        if (!tmp.startsWith(this.#http) && !tmp.endsWith(this.#hubpath)) {
            throw new Error(`${url}不是有效的http地址或不是以${this.#hubpath}结尾`);
        }
        let initkey = SClient.init(tmp, rndstr);
        if (callback) {
            this.subscribe(initkey, callback);
        }
        await SClient.start(initkey, true);
        this.#map.set(initkey, { count: 1 })
        // if (this.#map.has(initkey)) {
        //     this.#map.get(initkey).count += 1;
        // } else {
        //     this.#map.set(initkey, { count: 1 });
        // }
        
        return initkey;
    }

    /**
     * 注册订立逻辑服务
     * @param {string} initkey start method return value
     * @param {Function} callback receive data handler, callback function only one parameter, format: {type: string, group: string, Data: any }
     */
    subscribe(initkey, callback) {
        SClient.on(initkey, 'ReceiveMsg', callback);
    }

    /**
     * 推送数据
     * @param {string} initkey start method return value
     * @param {object} data 格式: {type: string, group: string, Data: any }
     */
    async publish(initKey, data) {
        if (initKey && data) {
            await SClient.invoke(initKey, 'SendMsg', data)
        }
    }

    /**
     * 注销
     * @param {string} initkey start method return value
     * @param {Function} callback
     */
    dispose(initKey, callback = null) {
        if (this.#map.has(initKey)) {
            if (callback) {
                try{
                    SClient.off(initKey, 'ReceiveMsg', callback);
                } catch{}
            }
            let obj = this.#map.get(initKey);
            obj.count -= 1;
            if (obj.count <= 0) {
                try{
                    SClient.dispose(initKey);
                }catch{}
            }
        }
    }
}

export const PubSub = new PublishSubscribe();